package net.sf.midollo.net.cgitunnel.client;

import java.net.URL;

import net.sf.midollo.io.buffer.BufferedIOStreamFactory;
import net.sf.midollo.io.log.LogIOStreamFactory;
import net.sf.midollo.io.printable.PrintableOutputStream;
import net.sf.midollo.net.httptunnel.client.HttpTunnelClientIOStreamFactory;
import net.sf.midollo.net.io.SocketIOStreamFactory;
import net.sf.midollo.net.protocol.tunnel.TunnelFactory;
import net.sf.midollo.net.server.AsyncAcceptHandler;
import net.sf.midollo.net.server.InetServer;
import net.sf.midollo.utils.Utils;

public class Main {

  public static final int BUFFER_SIZE_RESPONSE = 8 * 1024;
  public static final int BUFFER_SIZE_REQUEST_HTTP = BUFFER_SIZE_RESPONSE - 1024;
  public static final int BUFFER_SIZE_REQUEST_CGI = BUFFER_SIZE_REQUEST_HTTP - 16;

  public static void main(String[] args) {
    try {
      String strLocalPort = null;
      String strRemoteAddr = null;
      String strUrl = null;
      for (int idx = 0; idx < args.length; ++idx) {
        if (args[idx].compareTo("-p") == 0) {
          if (++idx < args.length) {
            strLocalPort = args[idx];
          }
        } else if (args[idx].compareTo("-r") == 0) {
          if (++idx < args.length)
            strRemoteAddr = args[idx];
        } else if (args[idx].compareTo("-u") == 0) {
          if (++idx < args.length)
            strUrl = args[idx];
        }
      }

      int localPort = Utils.parseInt(strLocalPort, 0);
      URL url = new URL(strUrl);
      Object[] parsedRemoteAddr = Utils.parseHostAndPort(strRemoteAddr);
      String host = Utils.getParsedHost(parsedRemoteAddr, "127.0.0.1");
      int port = Utils.getParsedPort(parsedRemoteAddr, 80);

      PrintableOutputStream printableOutputStream = new PrintableOutputStream(System.out);
      SocketIOStreamFactory socketIOStreamFactory = new SocketIOStreamFactory(url, 80);
      LogIOStreamFactory logIOStreamFactory = new LogIOStreamFactory(socketIOStreamFactory, printableOutputStream, printableOutputStream);
      HttpTunnelClientIOStreamFactory httpTunnelClientIOStreamFactory = new HttpTunnelClientIOStreamFactory(url, logIOStreamFactory);

      BufferedIOStreamFactory bufferedIOStreamFactory = new BufferedIOStreamFactory(httpTunnelClientIOStreamFactory, 0, BUFFER_SIZE_REQUEST_HTTP);
      CGITunnelClientIOStreamFactory cgiTunnelClientIOStreamFactory = new CGITunnelClientIOStreamFactory(bufferedIOStreamFactory, host, port);
      TunnelFactory protocolFactory = new TunnelFactory(cgiTunnelClientIOStreamFactory, BUFFER_SIZE_REQUEST_CGI, BUFFER_SIZE_RESPONSE);
      AsyncAcceptHandler acceptHandler = new AsyncAcceptHandler(protocolFactory);
      InetServer inetServer = new InetServer(localPort, acceptHandler);
      inetServer.run();

    } catch (Throwable ex) {
      ex.printStackTrace();
    }
  }
}
